/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.flexengine.sound;

import com.flexengine.logger.Logger;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author Luann R. Athayde
 * @version 1.0
 * @since 11/09/2012
 */
class LoopByteArrayInputStream extends InputStream {

    public static final int END_OF_STREAM = -0xffff;
    
    private byte    buffer[];
    private int     pos;
    private boolean closed;

    public LoopByteArrayInputStream(byte[] buffer) {
        this.buffer = buffer;
        this.pos    = 0;
        this.closed = false;
    }
    
    public LoopByteArrayInputStream(File inputFile) {
        this.pos = 0;
        try {
            try (FileInputStream in = new FileInputStream(inputFile)) {
                int size = in.available();
                buffer = new byte[size];
                in.read(buffer, 0, buffer.length);
            }
        } catch(IOException e) {
            Logger.logError(getClass().getSimpleName()+"(): "+e);
            this.buffer =  null;
            this.closed =  true;
        }
    }
    
    @Override
    public synchronized int read() {
        if( closed || buffer == null || pos>=buffer.length ) {
            return END_OF_STREAM;
        }
        int b = buffer[pos];
        pos++;
        return b;
    }

    @Override
    public synchronized void reset() {
        pos = 0;
    }

    @Override
    public synchronized int read(byte[] buffer, int offset, int lenght) throws IOException {
        if (this.buffer==null || buffer == null) {
            throw new NullPointerException();
        } else if (offset < 0 || lenght < 0 || lenght > buffer.length - offset) {
            throw new IndexOutOfBoundsException();
        } else if (lenght == 0) {
            return 0;
        } else if( closed ) {
            return -1;
        }
        // -- Clear the buffer...
        clear(buffer);
        // read...
        int bRead = read();
        // End of stream, then reset...
        if( bRead == END_OF_STREAM ) {
            reset();
            return read(buffer, offset, lenght);
        }
        //--
        buffer[offset] = (byte) bRead;
        int read = 1;
        for(;read<lenght;read++) {
            bRead = (byte) read();
            if( bRead == END_OF_STREAM ) {
                break;
            }
            buffer[offset+read] = (byte) bRead;
        }
        return read;
    }
    
    private synchronized void clear(byte[] buffer) throws NullPointerException {
        for(int i=0;i<buffer.length;i++) {
            buffer[i] = 0;
        }
    }
    
    @Override
    public void close() {
        closed = true;
        clear(buffer);
        pos = 0;
    }

    public boolean isClosed() {
        return closed;
    }

    @Override
    public long skip(long skip) {
        int tmp = buffer.length - pos;
        pos += skip;
        if( pos >= buffer.length ) {
            pos = 0;
            skip -= tmp;
            return skip(skip);
        }
        return skip;
    }

    @Override
    public int available() {
        if( closed ) {
            return -1;
        }
        return buffer.length;
    }
    
}
